<script setup>
import { GridLayout, GridItem } from "grid-layout-plus";
import { computed, ref, watch, onMounted, handleError, shallowRef } from "vue";
import MonitorDashboardLayout from "./components/MonitorDashboardLayout.vue";
import ResourceUsage from "./components/ResourceUsage.vue";
import { useMobileDetection } from "@/composables/useMobileDetection";
import AddComponentDrawer from "./components/AddComponentDrawer.vue";
import { Plus, Close } from '@element-plus/icons-vue'
import SvgIcon from "@/components/icon/SvgIcon.vue";
import { useUserStore } from "@/stores/userinfo";
import { editLayoutApi, getLayoutApi } from "@/api/layout";
import { hasCardPermission, componentMap } from "../../../config/cardConfig";
import { usePermissionStore } from "../../../stores/permission";

const { isMobile, isTablet, isPC } = useMobileDetection();
const colNum = computed(() => (isMobile.value || isTablet.value ? 1 : 3));
const userStore = useUserStore();

// 响应式布局
const layout = ref([]);
const filteredLayout = computed(() => {
  return layout.value.filter(item => hasCardPermission(item.component, usePermissionStore().userPermissions));
})
// 保存原始布局，用于取消时恢复
const originalLayout = ref([]);

// 将布局转换为移动端布局的函数
function convertToMobileLayout(layoutData) {
  return layoutData.map((item, index) => ({
    ...item,
    x: 0,
    y: index,
    w: 1,
    h: 1
  }));
}

// 监听移动端/平板状态变化
watch([isMobile, isTablet], ([newMobile, newTablet]) => {
  if ((newMobile || newTablet) && layout.value.length > 0) {
    // 切换到移动端或平板端时，转换当前布局为一列
    layout.value = convertToMobileLayout(layout.value);
  } else {
    // 切换回桌面端时，重新获取布局
    fetchLayout();
  }
  originalLayout.value = [...layout.value];
});

// 组件映射
const dropId = ref(null);

function handleAddComponent(component) {
  let maxId = -1;
  if (layout.value.length > 0) {
    layout.value.forEach(item => {
      const itemId = parseInt(item.i, 10);
      if (!isNaN(itemId) && itemId > maxId) {
        maxId = itemId;
      }
    });
  }
  const newId = String(maxId + 1);

  const newItem = {
    x: (isMobile.value || isTablet.value) ? 0 : layout.value.length % colNum.value,
    y: (isMobile.value || isTablet.value)
      ? layout.value.length
      : Math.floor(layout.value.length / colNum.value),
    w: 1,
    h: 1,
    i: newId,
    component: component,
  };

  layout.value.push(newItem);
}

// 移除组件
function removeItem(id) {
  const index = layout.value.findIndex((item) => item.i === id);
  if (index > -1) {
    layout.value.splice(index, 1);
    // 重新调整剩余组件的位置
    if (isMobile.value || isTablet.value) {
      layout.value = convertToMobileLayout(layout.value);
    }
  }
}

let isCustomLayout = ref(false);
let drawerVisible = ref(false);

// 计算是否显示添加按钮
const showAddButton = computed(() => isCustomLayout.value && !drawerVisible.value);

// 进入自定义模式
function enterCustomMode() {
  isCustomLayout.value = true;
  // 保存当前布局用于取消时恢复
  originalLayout.value = JSON.parse(JSON.stringify(layout.value));
}

// 修改保存布局的函数
async function saveLayout() {
  try {
    layoutLoading.value = true;
    // 将布局对象数组转换为字符串数组
    const layoutStrings = layout.value.map(item => JSON.stringify(item));

    await editLayoutApi({
      user_id: userStore.userinfo.id,
      layouts: layoutStrings
    });

    isCustomLayout.value = false;
    ElMessage({
      type: 'success',
      message: '布局保存成功！',
      duration: 2000
    });

    // 更新原始布局
    originalLayout.value = JSON.parse(JSON.stringify(layout.value));
  } catch (error) {
    handleError(error, '保存布局失败，请重试')
  } finally {
    layoutLoading.value = false;
  }
}
// 清空布局
function clearLayout() {
  layout.value = [];
  originalLayout.value = [];
  ElMessage({
    type: 'success',
    message: '已清空布局',
    duration: 2000
  });
}
// 取消保存
function cancelLayout() {
  ElMessage({
    type: "info",
    message: "已取消保存，布局已恢复",
    duration: 2000,
  });
  // 恢复原始布局
  layout.value = JSON.parse(JSON.stringify(originalLayout.value));
  isCustomLayout.value = false;
}

let layoutLoading = ref(false);
async function fetchLayout() {
  layoutLoading.value = true;
  try {
    const { data } = await getLayoutApi({
      id: userStore.userinfo.id
    });

    if (data && Array.isArray(data) && data.length > 0) {
      try {
        const parsedLayout = data.map(layoutStr => JSON.parse(layoutStr));

        const isValidLayout = parsedLayout.every(item =>
          item.hasOwnProperty('x') &&
          item.hasOwnProperty('y') &&
          item.hasOwnProperty('w') &&
          item.hasOwnProperty('h') &&
          item.hasOwnProperty('i') &&
          item.hasOwnProperty('component')
        );

        if (isValidLayout) {
          layout.value = isMobile.value ? convertToMobileLayout(parsedLayout) : parsedLayout;
          originalLayout.value = [...layout.value];
        } else {
          throw new Error('Invalid layout data structure');
        }
      } catch (parseError) {
        console.error('解析布局数据失败:', parseError);
        layout.value = []; // 解析失败时显示空状态
        originalLayout.value = [];
      }
    } else {
      // 如果没有保存的布局，显示空状态
      layout.value = [];
      originalLayout.value = [];
    }
  } catch (error) {
    handleError(error, '获取布局失败，请重试')
    layout.value = []; // 请求失败时显示空状态
    originalLayout.value = [];
  } finally {
    layoutLoading.value = false;
  }
}
const loadedComponents = ref({});

// 组件加载函数
function loadComponent(item) {
  if (!loadedComponents.value[item.i]) {
    loadedComponents.value[item.i] = true;
  }
}
onMounted(() => {
  fetchLayout();
});

</script>
<template>
  <div class="dashboard">
    <ResourceUsage style="margin-bottom: 16px"></ResourceUsage>
    <div style="margin-bottom: var(--gap-normal)">
      <MonitorDashboardLayout></MonitorDashboardLayout>
    </div>
    <div class="energy-title">
      <div class="title-actions">自定义图表</div>
      <div class="layout-actions">
        <el-button v-if="!isCustomLayout" @click="enterCustomMode" type="primary" size="small">
          <template #icon>
            <SvgIcon icon="customLayout"></SvgIcon>
          </template>
          自定义布局
        </el-button>
        <el-button v-if="isCustomLayout" @click="saveLayout" type="success" size="small">保存</el-button>
        <el-button v-if="isCustomLayout" @click="clearLayout" type="warning" size="small">清空</el-button>
        <el-button v-if="isCustomLayout" @click="cancelLayout" type="danger" size="small">取消保存</el-button>
      </div>
    </div>

    <!-- 主要内容区域 -->
    <div v-loading="layoutLoading" ref="wrapperRef" class="grid-layout-container">
      <!-- 没有布局时显示空状态 -->
      <template v-if="layout.length === 0">
        <el-card class="empty-layout-card">
          <div class="empty-layout-content">
            <el-empty description="暂无图表布局">
              <el-button type="primary" @click="drawerVisible = true">
                添加组件
              </el-button>
            </el-empty>
          </div>
        </el-card>
      </template>

      <!-- 有布局时显示网格布局 -->
      <template v-else>
        <GridLayout ref="gridLayoutRef" v-model:layout="layout" :margin="[8, 8]" :col-num="colNum" :row-height="300"
          :is-draggable="isCustomLayout" :is-resizable="isCustomLayout" :use-css-transforms="true"
          :vertical-compact="true" :class="{ 'custom-mode': isCustomLayout }">
          <template v-for="item in filteredLayout" :key="item.i">
            <GridItem v-memo="[item.x, item.y, item.w, item.h, isCustomLayout]" drag-allow-from=".vue-draggable-handle"
              drag-ignore-from=".no-drag" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :i="item.i">
              <div style="height: 100%; width: 100%; position: relative">
                <el-card v-lazy-load="() => loadComponent(item)"
                  body-style="height: 100%;width: 100%;display: flex;flex-direction: column;padding:16px 32px"
                  style="height: 100%; width: 100%">
                  <div v-if="isCustomLayout && !isMobile.value && !isTablet.value" class="vue-draggable-handle"></div>
                  <div v-if="isCustomLayout" class="remove-button" @click="removeItem(item.i)">
                    <el-icon>
                      <Close />
                    </el-icon>
                  </div>
                  <component v-if="item.i !== dropId && loadedComponents[item.i]" :is="componentMap[item.component]" />
                </el-card>
              </div>
            </GridItem>
          </template>
        </GridLayout>
      </template>
    </div>

    <!-- 新增固钉按钮 -->
    <el-affix position="bottom" :offset="120" v-if="showAddButton">
      <el-button type="primary" circle class="add-button" @click="drawerVisible = true">
        <el-icon>
          <Plus />
        </el-icon>
      </el-button>
    </el-affix>


    <AddComponentDrawer @add-component="handleAddComponent" v-model="drawerVisible" />
  </div>
</template>

<style scoped>
.vgl-layout.custom-mode::before {
  position: absolute;
  margin: 4px;
  width: calc(100% - 4px);
  height: calc(100% - 4px);
  content: "";
  background-image: linear-gradient(to right,
      var(--el-border-color) 1px,
      transparent 1px),
    linear-gradient(to bottom, var(--el-border-color) 1px, transparent 1px);
  background-repeat: repeat;
  background-size: calc(calc(100% - 4px) / v-bind(colNum)) calc(300px + 8px);
  pointer-events: none;
}

.vue-draggable-handle {
  position: absolute;
  top: 8px;
  left: 8px;
  width: 20px;
  height: 20px;
  background-color: var(--el-color-primary);
  border-radius: 4px;
  cursor: move;
  z-index: 1;
  transition: all 0.3s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.vue-draggable-handle:hover {
  transform: scale(1.1);
  background-color: var(--el-color-primary-dark-2);
}

.vue-draggable-handle::before,
.vue-draggable-handle::after {
  content: "";
  position: absolute;
  width: 10px;
  height: 2px;
  background-color: white;
  border-radius: 1px;
}

.vue-draggable-handle::before {
  box-shadow: 0 4px 0 white, 0 -4px 0 white;
}

.vue-draggable-handle::after {
  transform: rotate(90deg);
  box-shadow: 0 4px 0 white, 0 -4px 0 white;
}

.dashboard {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  padding-bottom: 16px;
}

.grid-layout-container {
  transform: translate(-8px);
  width: calc(100% + 16px);
}

.energy-title {
  font-size: var(--font-size-medium);
  font-weight: bold;
  height: 58px;
  padding-bottom: 8px;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: flex-end;
  width: 100%;
  background-color: var(--color-background);
}

.remove-button {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  cursor: pointer;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--el-color-danger);
  color: white;
  border-radius: 50%;
  transition: all 0.3s;
}

.remove-button:hover {
  background-color: var(--el-color-danger-dark-2);
  transform: scale(1.1);
}

/* 新增固钉按钮样式 */
.add-button {
  width: 50px;
  height: 50px;
  font-size: 20px;
  box-shadow: var(--el-box-shadow-light);
  transition: all 0.3s;
  position: fixed;
  right: 30px;
  z-index: 999;
}

.add-button:hover {
  transform: scale(1.1);
  box-shadow: var(--el-box-shadow);
}


/* 移动端适配 */
@media screen and (max-width: 768px) {
  .vgl-layout.custom-mode::before {
    background-size: calc(calc(100% - 4px) / 1) calc(300px + 8px);
  }

  .vue-draggable-handle {
    top: 4px;
    left: 4px;
    width: 16px;
    height: 16px;
  }

  .vue-draggable-handle::before,
  .vue-draggable-handle::after {
    width: 8px;
  }

  .vue-draggable-handle::before {
    box-shadow: 0 3px 0 white, 0 -3px 0 white;
  }

  .vue-draggable-handle::after {
    box-shadow: 0 3px 0 white, 0 -3px 0 white;
  }

  .grid-layout-container {
    transform: translate(-4px);
    width: calc(100% + 8px);
  }

  .energy-title {
    height: 48px;
    padding-bottom: 4px;
  }

  .remove-button {
    top: 4px;
    right: 4px;
    width: 20px;
    height: 20px;
  }

  .add-button {
    width: 40px;
    height: 40px;
    font-size: 16px;
    right: 20px;
  }


}
</style>